package impl;

import interfaces.ChatProxy;
import interfaces.ChatServer;
import interfaces.ClientProxy;

import java.rmi.Naming;
import java.rmi.RemoteException;
import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;
import java.rmi.server.UnicastRemoteObject;
import java.util.HashMap;

/**
 * Methodimplementation of chatserver.
 * Stores all chatproxy objects and spreads messages to all clients.
 * Implements methods for clients to subscribe and unsubcribe
 *
 * @author Dominik Korittki
 * @author Steffen Grushka
 * @version 0.1
 */
public class ChatServerImpl extends UnicastRemoteObject implements ChatServer {

	private static final long serialVersionUID = 1L;
	private HashMap<String, ChatProxyImpl> clients;

	public ChatServerImpl() throws RemoteException {
		clients = new HashMap<String, ChatProxyImpl>();
	}
	
	@Override
	public ChatProxy subscribeUser(String username, ClientProxy handle) throws RemoteException {
		
		if(clients.containsKey(username) || username.equals("System")) {
			System.out.println("username " + username + " is already in use. Abort subscribe attempt.");
			return null;
		}
		
		if(handle == null) {
			System.out.println("client with name " + username + " handle object is null. Abort subscribe attempt.");
			return null;
		}
		
		ChatProxyImpl chatproxy = new ChatProxyImpl(username, handle, this);
		clients.put(username, chatproxy);
		System.out.println("client " + username + " successfully subscribed.");
		spreadMessage("System", username + " has joined.");
		
		return chatproxy;
	}
	
	@Override
	public boolean unsubscribeUser(String username) throws RemoteException {
		
		if(!clients.containsKey(username))
			return false;
		
		clients.remove(username);
		System.out.println("client successfully unsubscribed: " + username);
		spreadMessage("System", username + " has left.");
		return true;
	}
	
	/**
	 * when called a message will be send to all listet clients
	 * @param username username of message author
	 * @param message actual message to spread
	 */
	public void spreadMessage(String username, String message) {
		System.out.println("Spread message: " + username + "->" + message);
		for(String i : clients.keySet()) {
			ChatProxyImpl actClient = clients.get(i);
			ClientProxy client = actClient.getClientproxy();
			try {
				client.receiveMessage(username, message);
			} catch (Exception e) {
				System.err.println("Could not spread message to a client.");
				e.printStackTrace();
			}
		}
	}

	/**
	 * Start rmi registry and register ChatServer object
	 * @param args
	 */
	public static void main(String[] args) {
		try {
			LocateRegistry.createRegistry(Registry.REGISTRY_PORT); //Registry starten
			Naming.rebind("ChatServer", new ChatServerImpl()); //Als "ChatServer" registrieren
			System.out.println("server successfully registered at rmi registry called 'ChatServer'.");
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
}
